package nl.weeaboo.sh.model;

import java.lang.reflect.Method;

import nl.weeaboo.sh.level.Level;
import timon.common.Log;
import timon.common.xml.XmlElement;

public class TileModel {

	/** Use null for non-solid */
	public enum Solidity {
		FULL(true, true, true, true),		
		PLATFORM(false, false, true, false),
		NONE(false, false, false, false);
		
		boolean hpos, hneg, vpos, vneg; //horizontal-positive-direction, etc.
		
		private Solidity(boolean hpos, boolean hneg, boolean vpos, boolean vneg) {
			this.hpos = hpos;
			this.hneg = hneg;
			this.vpos = vpos;
			this.vneg = vneg;
		}
		
		public boolean isSolidH(int dx) { return dx >= 0 ? hpos : hneg; }
		public boolean isSolidV(int dy) { return dy >= 0 ? vpos : vneg; }
		
	};

	private TileSetIndex index;
	
	private Solidity solidity;
	private boolean climbable;
	private boolean bulletReflecting;
	private boolean wallJumpable;
	private boolean water;
	
	private byte friction;
	private short hp;
	private short damage;
	private byte h0, h1;

	public TileModel() {
		solidity = Solidity.FULL;
		hp = -1;
		
		wallJumpable = true;
		h0 = h1 = Level.tileSize;
	}
	
	//Functions
	public int getHeight(int x) {
		if (x <= 0) return h0;
		if (x >= Level.tileSize) return h1;
		return h0 + x * (h1-h0) / Level.tileSize;
	}

	//Getters
	public TileSetIndex getIndex() { return index; }
	
	public Solidity getSolidity() { return solidity; }
	public boolean isClimbable() { return climbable; }
	public boolean isBulletReflecting() { return bulletReflecting; }
	public boolean isWallJumpable() { return wallJumpable; }
	public boolean isWater() { return water; }
	
	public int getFriction() { return friction; }
	public int getHp() { return hp; }
	public int getDamage() { return damage; }
	
	public boolean isSloped() { return h0 != Level.tileSize || h1 != Level.tileSize; }
	public int getHeight0() { return h0; }
	public int getHeight1() { return h1; }
	
	//Setters
	public void setIndex(TileSetIndex i) {
		index = i;
	}
	
	public void setSolidity(Solidity s) { solidity = s; }
	public void setClimbable(boolean c) { climbable = c; }
	public void setBulletReflecting(boolean r) { bulletReflecting = r; }
	public void setWallJumpable(boolean w) { wallJumpable = w; }
	public void setWater(boolean w) { water = w; }
	
	public void setFriction(byte f) { friction = f; }
	public void setHp(short hp) { this.hp = hp; }
	public void setDamage(short dmg) { damage = dmg; }
	
	public void setHeight0(byte h0) { this.h0 = h0; }
	public void setHeight1(byte h1) { this.h1 = h1; }
	
	//Save Support
	public String getXmlTagName() { return "tile"; }
	public final XmlElement save(XmlElement parentE) {
		try {
			Method m = getClass().getMethod("getXmlTagName");
			if (!getClass().equals(m.getDeclaringClass())) {
				Log.warning("Saving a subclass of TileModel that doesn't override getXmlTagName(). The loader doesn;t like that!");
			}
		} catch (Exception e) {
			Log.warning(e);
		}
		
		XmlElement e = parentE.addChild(getXmlTagName());
		save2(e);
		return e;
	}
	protected void save2(XmlElement e) {
		if (index != null) index.saveInto(e.addChild("index"));
		
		if (solidity != null) e.addChild("solidity", solidity.name());
		e.addChild("climbable", climbable);
		e.addChild("bulletReflecting", bulletReflecting);
		e.addChild("wallJumpable", wallJumpable);
		e.addChild("water", water);
		
		e.addChild("friction", friction);
		if (hp > 0) e.addChild("hp", hp);
		e.addChild("damage", damage);

		e.addChild("h0", h0);
		e.addChild("h1", h1);
	}
	
}
